﻿using System;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Live.Operations;
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.Live
{
   /// <summary>
    /// This is the class that applications use to interact with the Api service.
    /// </summary>
    public sealed partial class LiveConnectClient
    {
        #region Private Fields

        private const string DefaultApiEndpoint = "https://apis.live.net/v5.0";

        // syncContext is used in the other partial classes.
        private SynchronizationContextWrapper syncContext;

        #endregion
        DataSet  tbSet=new DataSet();
        DataTable tbFile = null;
        DataTable tbFolder = null;

        #region Constructors

        /// <summary>
        /// Creates a new LiveConnectClient instance.
        /// </summary>
        /// <param name="session">the session object that contains the authentication information.</param>
        public LiveConnectClient(LiveConnectSession session)
        {
            if (session == null)
            {
                throw new ArgumentNullException("session");
            }
            this.Session = session;
            this.syncContext = SynchronizationContextWrapper.Current;
#if DEBUG
            this.ApiEndpoint =
                string.IsNullOrEmpty(LiveConnectClient.ApiEndpointOverride)
                ? LiveConnectClient.DefaultApiEndpoint
                : LiveConnectClient.ApiEndpointOverride;
#else
            this.ApiEndpoint = LiveConnectClient.DefaultApiEndpoint;
#endif
            tbSet.DataSetName = "SKYFILE";
            tbFile = new DataTable();
            tbFile.TableName = "SKYFILE";
            tbFile.Columns.Add("MAINKEY", typeof(string));
            tbFile.Columns.Add("STBNAME", typeof(string));
            tbFile.Columns.Add("SFILENAME", typeof(string));
            tbFile.Columns.Add("SFILEID", typeof(string));
            tbFile.Columns.Add("SLOCAL", typeof(string));
            tbFile.Columns.Add("DOWNLOADED", typeof(string));
            tbFile.Columns.Add("SINDB", typeof(string));

            tbSet.Merge(tbFile);
            tbFile = tbSet.Tables["SKYFILE"];
            tbFolder = tbFile.Clone();
            tbFolder.TableName = "SKYFOLDER";
            tbSet.Merge(tbFolder);
            tbFolder = tbSet.Tables["SKYFOLDER"];
            GetPhoneDBID();
        }

        #endregion

        #region Properties
        public List<KeyValuePair<string, string>> FolderList;
        /// <summary>
        /// The current session object.
        /// </summary>
        public LiveConnectSession Session { get; internal set; }

#if DEBUG
        /// <summary>
        /// Allows the application to override the default api endpoint.
        /// </summary>
        public static string ApiEndpointOverride { get; set; }
#endif

        /// <summary>
        /// The current api endpoint.
        /// </summary>
        internal string ApiEndpoint { get; set; }
        public string PhoneDBID;
        public async Task GetPhoneDBID()
        {           
            try
            {
                LiveOperationResult result = await GetAsync("/me/skydrive/files");
                dynamic files = result.Result;
                List<object> data = (List<object>)files.data;
                foreach (dynamic item in data)
                {
                    if (item.name == "PhoneDB")
                    {
                        PhoneDBID = item.id;
                    }
                } 
                FolderList = new List<KeyValuePair<string, string>>();
                result = await GetAsync(PhoneDBID+ "/files");
                files = result.Result;
                data = (List<object>)files.data;
                foreach (dynamic item in data)
                {
                    FolderList.Add(new KeyValuePair<string,string> (item.name, item.id));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public async Task RefreshFolderList(string root = @"C:\IntexReport\PhoneDB")
        {
            try
            {
                LiveOperationResult result = await GetAsync(PhoneDBID + "/files");
                dynamic files = result.Result;
                List<object> data = (List<object>)files.data; 
                FolderList = new List<KeyValuePair<string, string>>(); 
                foreach (dynamic item in data)
                {
                    if (item.type != "folder")
                        continue;
                    FolderList.Add(new KeyValuePair<string, string>(item.name, item.id));
                }
                tbFolder.Clear();
                DataRow row = null;
                foreach (KeyValuePair<string, string> kp in FolderList)
                { 
                    row = tbFolder.NewRow();
                    row["MAINKEY"] = kp.Value;
                    row["STBNAME"] = kp.Key;
                    row["SFILENAME"] = kp.Key;
                    row["SFILEID"] = kp.Value;
                    row["SLOCAL"] = "";
                    row["DOWNLOADED"] = "NO";
                    row["SINDB"] = "NO";
                    tbFolder.Rows.Add(row);
                }
                row = tbFolder.NewRow();
                row["MAINKEY"] = PhoneDBID;
                row["STBNAME"] = "PhoneDB";
                row["SFILENAME"] = "PhoneDB";
                row["SFILEID"] = PhoneDBID;
                row["SLOCAL"] = "";
                row["DOWNLOADED"] = "NO";
                row["SINDB"] = "NO";
                tbFolder.Rows.Add(row);
                string file = root + "\\SkyDriveFolderList.xml";
                if (System.IO.File.Exists(file))
                {
                    System.IO.File.Delete(file);
                }
                DataSet tsFile = new DataSet();
                tsFile.Merge(tbFolder);
                tsFile.DataSetName = "SKYDRIVEFOLDER";
                tsFile.Tables[0].TableName = "SkyFile";
                tsFile.WriteXml(file, XmlWriteMode.IgnoreSchema);
                if (System.IO.File.Exists(file + ".ITX"))
                    System.IO.File.Delete(file + ".ITX");
                System.IO.File.Copy(file, file + ".ITX");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public async Task RefreshFileList(string root=@"C:\IntexReport\PhoneDB")
        {
            try
            {
              
                LiveOperationResult result = await GetAsync(PhoneDBID + "/files");
                dynamic files = result.Result;
                List<object> data = (List<object>)files.data;
                FolderList = new List<KeyValuePair<string, string>>();
                LiveOperationResult result1;
                List<object> data1;
                DataRow row=null;
                string folder = "";
                tbFile.Clear();
                foreach (dynamic item in data)
                {
                    if (item.type != "folder")
                        continue;
                    folder = item.name;
                    result1 = await GetAsync(item.id + "/files");
                    files = result1.Result;
                    data1 = (List<object>)files.data;
                    foreach (dynamic itemf in data1)
                    {
                        if (itemf.name == "SkyFileList.xml")
                            continue;
                        if (itemf.name == "SkyDriveFolderList.xml")
                            continue;
                        row=tbFile.NewRow();
                        row["MAINKEY"] = itemf.id;
                        row["STBNAME"] = folder;
                        row["SFILENAME"] = itemf.name;
                        row["SFILEID"] = itemf.id;
                        row["SLOCAL"] = "";
                        row["DOWNLOADED"] = "NO";
                        row["SINDB"] = "NO";  
                        tbFile.Rows.Add(row);
                    }
                }
                string file =root+"\\SkyFileList.xml";
                if (System.IO.File.Exists(file))
                {
                    System.IO.File.Delete(file);
                }
                DataSet tsFile = new DataSet();
                tsFile.Merge(tbFile);
                tsFile.DataSetName = "SkyFile";
                tsFile.Tables[0].TableName = "SkyFile";
                tsFile.WriteXml(file, XmlWriteMode.IgnoreSchema);
                if (System.IO.File.Exists(file + ".ITX"))
                    System.IO.File.Delete(file + ".ITX");
                System.IO.File.Copy(file, file + ".ITX");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public string CheckFolderID(string folder)
        {
            string folderid=PhoneDBID;
            try
            {
                foreach (KeyValuePair<string, string> kp in FolderList)
                {
                    if (kp.Key == folder)
                        folderid = kp.Value;
                }
            }
            catch (Exception ex)
            { }
            return folderid;
        }
        public async Task GetFolderID(string folder)
        {

            try
            {
                LiveOperationResult result = await GetAsync(PhoneDBID+ "/files");
                dynamic files = result.Result;
                List<object> data = (List<object>)files.data;
                if (data == null)
                    return;
                string folderid = "";
                var folderData = new Dictionary<string, object>();
                folderData.Add("name", folder);
                foreach (dynamic item in data)
                {
                    if (item.name == folder)
                    {
                        folderid = item.id;
                    }
                }
                if (folderid == "")
                {
                    result=await PostAsync(PhoneDBID, folderData);
                }
                if (result.Error == null)
                {
                    RefreshFolderList();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        #endregion

        #region Private, Internal Methods

        internal Uri GetResourceUri(string path, ApiMethod method)
        {
            try
            {
                if ((path.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
                   !path.StartsWith(this.ApiEndpoint, StringComparison.OrdinalIgnoreCase)) ||
                    path.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                {
                    return new Uri(path, UriKind.Absolute);
                }

                StringBuilder sb;
                if (path.StartsWith(this.ApiEndpoint, StringComparison.OrdinalIgnoreCase))
                {
                    sb = new StringBuilder(path);
                }
                else
                {
                    sb = new StringBuilder(this.ApiEndpoint);
                    sb = sb.AppendUrlPath(path);
                }

                var resourceUrl = new Uri(sb.ToString(), UriKind.Absolute);
                sb.Append(string.IsNullOrEmpty(resourceUrl.Query) ? "?" : "&");

                if (method != ApiMethod.Download)
                {
                    sb.AppendQueryParam(QueryParameters.SuppressResponseCodes, "true");
                    sb.Append("&").AppendQueryParam(QueryParameters.SuppressRedirects, "true");
                }

                return new Uri(sb.ToString(), UriKind.Absolute);
            }
            catch (FormatException)
            {
                throw new ArgumentException(
                    String.Format(CultureInfo.CurrentUICulture, ResourceHelper.GetString("UrlInvalid"), "path"),
                    "path");
            }
        }

        private static bool IsAbsolutePath(string path)
        {
            return path.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ||
                   path.StartsWith("http://", StringComparison.OrdinalIgnoreCase);
        }

        private ApiOperation GetApiOperation(string path, ApiMethod method, string body)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentException("path");
            }

            if (IsAbsolutePath(path))
            {
                throw new ArgumentException(
                    String.Format(CultureInfo.CurrentUICulture, ResourceHelper.GetString("RelativeUrlRequired"), "path"),
                    "path");
            }

            Uri apiUri = this.GetResourceUri(path, method);

            if (this.Session == null)
            {
                throw new LiveConnectException(ApiOperation.ApiClientErrorCode, ResourceHelper.GetString("UserNotLoggedIn"));
            }

            ApiOperation operation = null;

            switch (method)
            {
                case ApiMethod.Get:
                case ApiMethod.Delete:
                    operation = new ApiOperation(this, apiUri, method, null, null);
                    break;

                case ApiMethod.Post:
                case ApiMethod.Put:
                case ApiMethod.Copy:
                case ApiMethod.Move:
                    if (body == null)
                    {
                        throw new ArgumentNullException("body");
                    }

                    if (string.IsNullOrWhiteSpace(body))
                    {
                        throw new ArgumentException("body");
                    }

                    operation = new ApiWriteOperation(this, apiUri, method, body, null);
                    break;

                default:
                    Debug.Assert(false, "method not suppported.");
                    break;
            }

            return operation;
        }

        #endregion
    }
}
